/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.support;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.lang.Nullable;

/**
 * Delegate for AbstractApplicationContext's post-processor handling.
 *
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 4.0
 */
final class PostProcessorRegistrationDelegate {

	private PostProcessorRegistrationDelegate() {
	}

	/**
	 * 执行 BeanFactoryPostProcessor 接口实现类的 postProcessBeanFactory 方法。此方法会首先尝试将 BeanDefinitionRegistryPostProcessor 接口的实现类
	 * 应用于 BeanDefinitionRegistry，随后会将 BeanFactoryPostProcessor 接口的所有实现类应用于 BeanFactory。
	 *
	 * @param beanFactory                   要处理的 BeanFactory 实例，必须是 ConfigurableListableBeanFactory 接口的实现。
	 * @param beanFactoryPostProcessors     要应用的 BeanFactoryPostProcessor 实现列表。
	 */
	public static void invokeBeanFactoryPostProcessors(
	        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	    // 首先，应用实现 BeanDefinitionRegistryPostProcessor 接口的处理器
	    Set<String> processedBeans = new HashSet<>();

	    if (beanFactory instanceof BeanDefinitionRegistry) {
	        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
	        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
	        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

	        // 拆分实现 BeanDefinitionRegistryPostProcessor PriorityOrdered、Ordered 接口的 和其他
	        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
	            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
	                BeanDefinitionRegistryPostProcessor registryProcessor =
	                        (BeanDefinitionRegistryPostProcessor) postProcessor;
					//
	                registryProcessor.postProcessBeanDefinitionRegistry(registry);
	                registryProcessors.add(registryProcessor);
	            }
	            else {
	                regularPostProcessors.add(postProcessor);
	            }
	        }

	        // 分别按 PriorityOrdered、Ordered 和无序处理 BeanDefinitionRegistryPostProcessor
	        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

	        // 处理实现 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor
	        String[] postProcessorNames =
	                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
	        for (String ppName : postProcessorNames) {
	            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
	                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
	                processedBeans.add(ppName);
	            }
	        }
	        sortPostProcessors(currentRegistryProcessors, beanFactory);
	        registryProcessors.addAll(currentRegistryProcessors);
			//遍历并执行给定的BeanDefinitionRegistryPostProcessor集合，每个处理器都会被调用其postProcessBeanDefinitionRegistry方法。
	        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
	        currentRegistryProcessors.clear();

	        // 处理实现 Ordered 接口的 BeanDefinitionRegistryPostProcessor
	        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
	        for (String ppName : postProcessorNames) {
	            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
	                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
	                processedBeans.add(ppName);
	            }
	        }
	        sortPostProcessors(currentRegistryProcessors, beanFactory);
	        registryProcessors.addAll(currentRegistryProcessors);
	        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
	        currentRegistryProcessors.clear();

	        // 处理剩余的 BeanDefinitionRegistryPostProcessor，直到没有新的处理器出现
	        boolean reiterate = true;
	        while (reiterate) {
	            reiterate = false;
	            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
	            for (String ppName : postProcessorNames) {
	                if (!processedBeans.contains(ppName)) {
	                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
	                    processedBeans.add(ppName);
	                    reiterate = true;
	                }
	            }
	            sortPostProcessors(currentRegistryProcessors, beanFactory);
	            registryProcessors.addAll(currentRegistryProcessors);
	            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
	            currentRegistryProcessors.clear();
	        }

	        // 现在，调用所有已处理处理器的 postProcessBeanFactory 方法
	        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
	        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	    }
	    else {
	        // 如果 beanFactory 不是 BeanDefinitionRegistry 实例，则直接应用所有 BeanFactoryPostProcessor
	        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	    }

	    // 清理 BeanFactory 中的 BeanDefinition 合并缓存，因为处理器可能会修改原始元数据
	    beanFactory.clearMetadataCache();
	}

	/**
	 * 注册BeanPostProcessor到给定的bean工厂和应用上下文。
	 * 这个过程包括注册一个BeanPostProcessorChecker来监控Bean的创建过程，
	 * 以及根据优先级将所有的BeanPostProcessor分类并注册。
	 *
	 * @param beanFactory 提供bean实例和类型匹配的bean工厂。
	 * @param applicationContext 应用上下文，用于注册应用监听器的BeanPostProcessor。
	 */
	public static void registerBeanPostProcessors(
	        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

	    // 获取所有实现BeanPostProcessor接口的bean名称
	    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

	    // 注册一个BeanPostProcessorChecker，用于在BeanPostProcessor实例化时记录信息日志，
	    // 即当一个bean不被所有BeanPostProcessor处理时。
	    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	    // 将BeanPostProcessor分为优先级排序、有序和无序三类
	    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	    List<String> orderedPostProcessorNames = new ArrayList<>();
	    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	    for (String ppName : postProcessorNames) {
	        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
	            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
	            priorityOrderedPostProcessors.add(pp);
	            if (pp instanceof MergedBeanDefinitionPostProcessor) {
	                internalPostProcessors.add(pp);
	            }
	        }
	        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
	            orderedPostProcessorNames.add(ppName);
	        }
	        else {
	            nonOrderedPostProcessorNames.add(ppName);
	        }
	    }

	    // 分别注册实现PriorityOrdered、Ordered和无优先级的BeanPostProcessor
	    // 首先注册实现PriorityOrdered的BeanPostProcessor
	    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//放入 List<BeanPostProcessor> beanPostProcessors
	    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	    // 注册实现Ordered的BeanPostProcessor
	    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	    for (String ppName : orderedPostProcessorNames) {
	        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
	        orderedPostProcessors.add(pp);
	        if (pp instanceof MergedBeanDefinitionPostProcessor) {
	            internalPostProcessors.add(pp);
	        }
	    }
	    sortPostProcessors(orderedPostProcessors, beanFactory);
	    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

	    // 注册剩余的无序BeanPostProcessor
	    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	    for (String ppName : nonOrderedPostProcessorNames) {
	        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
	        nonOrderedPostProcessors.add(pp);
	        if (pp instanceof MergedBeanDefinitionPostProcessor) {
	            internalPostProcessors.add(pp);
	        }
	    }
	    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

	    // 最后，注册所有的内部BeanPostProcessor
	    sortPostProcessors(internalPostProcessors, beanFactory);
	    registerBeanPostProcessors(beanFactory, internalPostProcessors);

	    // 重新注册用于检测内部bean作为ApplicationListener的BeanPostProcessor，
	    // 将其移到处理器链的末尾，以便捕获代理等。
	    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
	private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
		// Nothing to sort?
		if (postProcessors.size() <= 1) {
			return;
		}
		Comparator<Object> comparatorToUse = null;
		if (beanFactory instanceof DefaultListableBeanFactory) {
			comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
		}
		if (comparatorToUse == null) {
			comparatorToUse = OrderComparator.INSTANCE;
		}
		postProcessors.sort(comparatorToUse);
	}

	/**
	 * Invoke the given BeanDefinitionRegistryPostProcessor beans.
	 */
	/**
	 * 调用给定的BeanDefinitionRegistryPostProcessor Bean。
	 * 这个方法的作用是遍历并执行给定的BeanDefinitionRegistryPostProcessor集合，每个处理器都会被调用其postProcessBeanDefinitionRegistry方法。
	 *
	 * @param postProcessors BeanDefinitionRegistryPostProcessor对象的集合，这些对象将被调用以处理Bean定义注册表。
	 * @param registry Bean定义注册表，是Bean定义注册和查询的核心接口。
	 */
	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		// 遍历所有给定的BeanDefinitionRegistryPostProcessor，依次调用它们的postProcessBeanDefinitionRegistry方法。
		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}


	/**
	 * Invoke the given BeanFactoryPostProcessor beans.
	 * 调用给定的实例工厂后处理器
	 */
	private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanFactory(beanFactory);
		}
	}

	/**
	 * Register the given BeanPostProcessor beans.
	 */
	private static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

		for (BeanPostProcessor postProcessor : postProcessors) {
			beanFactory.addBeanPostProcessor(postProcessor);
		}
	}


	/**
	 * BeanPostProcessor that logs an info message when a bean is created during
	 * BeanPostProcessor instantiation, i.e. when a bean is not eligible for
	 * getting processed by all BeanPostProcessors.
	 */
	private static final class BeanPostProcessorChecker implements BeanPostProcessor {

		private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);

		private final ConfigurableListableBeanFactory beanFactory;

		private final int beanPostProcessorTargetCount;

		public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
			this.beanFactory = beanFactory;
			this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
		}

		@Override
		public Object postProcessBeforeInitialization(Object bean, String beanName) {
			return bean;
		}

		@Override
		public Object postProcessAfterInitialization(Object bean, String beanName) {
			if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
					this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
				if (logger.isInfoEnabled()) {
					logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
							"] is not eligible for getting processed by all BeanPostProcessors " +
							"(for example: not eligible for auto-proxying)");
				}
			}
			return bean;
		}

		private boolean isInfrastructureBean(@Nullable String beanName) {
			if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {
				BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
				return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE);
			}
			return false;
		}
	}

}
